package com.education.filter;

import com.alibaba.fastjson.JSON;
import com.education.auth.utlis.JwtUtils;
import com.education.common.pojo.AjaxResult;
import com.education.config.FilterProperties;
import com.education.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author:
 * @create: 2018-07-08 15:05
 **/
@Slf4j
@Component
@EnableConfigurationProperties({JwtProperties.class, FilterProperties.class})
public class LoginFilter extends ZuulFilter {

    @Autowired
    private JwtProperties jwtProp;
    @Autowired
    private FilterProperties filterProp;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 3;
    }

    /**
     * 根据url地址判断是否开启过滤器
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        HttpServletRequest request = attributes.getRequest();
        //获取请求上下文
        //RequestContext ctx = RequestContext.getCurrentContext();
        //HttpServletRequest request = ctx.getRequest();
        String requestURI = request.getRequestURI();
        log.info("请求url:" + requestURI);
        if (requestURI.startsWith("/api/auth")) {
            return false;
        }
        // 判断路径是否放行
        //isAllowPath(requestURI);
        //拦截
        //return true;
        //放行
        return false;
    }

    /**
     * 判断路径放行
     *
     * @param uri
     * @return
     */
    private boolean isAllowPath(String uri) {
        //获取定义好的路径判断是否放行
        /*List<String> allowPaths = filterProp.getAllowPaths();
        for (String path : allowPaths) {
            if (uri.startsWith(path)) {
                return true;
            }
        }
        return false;*/
        return true;
    }

    /**
     * 具体过滤器的执行逻辑
     *
     * @return
     */
    @Override
    public Object run() {
        // 获取请求上下文
        RequestContext currentContext = RequestContext.getCurrentContext();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        HttpServletRequest request = attributes.getRequest();

        String token = request.getHeader("token");
        response.setContentType("application/json;charset=utf-8");
        //1.判断请求是否携带token
        if (null == token) {
            AjaxResult error = AjaxResult.error(401, "Please add token!");
            PrintWriter out = null;
            try {
                out = response.getWriter();
                out.print(JSON.toJSONString(error));
                out.flush();
                out.close();
                currentContext.setSendZuulResponse(false);
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                currentContext.setSendZuulResponse(false);
                return null;
            }
        }
        //2.校验token的有效性
        try {
            JwtUtils.getInfoFromToken(token, jwtProp.getPublicKey());
        } catch (Exception e) {
            PrintWriter out = null;
            String errorStr = "token happen exception!";
            if (e instanceof ExpiredJwtException) {
                errorStr = e.getMessage();
            }
            AjaxResult error = AjaxResult.error(401, errorStr);

            try {
                out = response.getWriter();
                out.print(JSON.toJSONString(error));
                out.flush();
                out.close();
                currentContext.setSendZuulResponse(false);
                return null;
            } catch (IOException e1) {
                e.printStackTrace();
                currentContext.setSendZuulResponse(false);
                return null;
            }
            // 无效的token，返回403
            //currentContext.setResponseStatusCode(403);
            // 不继续路由和响应
            //currentContext.setSendZuulResponse(false);
            //currentContext.setResponseBody();
        }
        return null;
    }
}